/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * $Id: AlarmTypes.hpp,v 1.6 2009-05-13 07:18:16 amaula Exp $
 *
 * \file
 * \brief Describes the Alarm interface types.
 * \author Antti Maula <antti.maula@tkk.fi>
 *
 */
#ifndef _MACI_ALARMTYPES_HPP_
#define _MACI_ALARMTYPES_HPP_
#include <inttypes.h>
#include <string.h>
#include <string>
#include "ownutils.h"
#include "owndebug.h"

namespace MaCI {

  /** MaCI - Alarm interface.
   *
   * This namespace contains all the methods and types related
   * to the Alarm interface.
   */
  namespace Alarm {
    
    /** Enumeration types for Alarm data elements.
     */
    enum EAlarmType { 
      KTypeUnknown               = -1, ///< Unkown type.
      KTypeTimestamp             = 1,  ///< Common::TTimestamp element.
      KTypeCommand               = 2,  ///< TCommand element.
      KTypeAlarmEvent            = 3,  ///< TAlarmEvent element.
      KTypeText                  = 4,  ///< TText element.
      KTypeHeadingText           = 5,  ///< Like TText element, but should be shorter
      KTypeSourceNameText        = 6,  ///< Freeform source identifier, contained in TText.
    };
    
    
    /** Enumerations for Alarm Command.
     */
    enum EAlarmCommand { 
      /// Acknowledge event. 'data' field contains event ID.
      KCommandUserAckEvent         = 1, 


      /// User answers 'Yes'. 'data' field contains event ID.
      KCommandUserQuestionReplyYes = 2,


      /// User answers 'No'. 'data' field contains event ID. 
      KCommandUserQuestionReplyNo  = 3,


      /// User doesn't answer anything. Equals to timeout, but is
      /// faster for the server side. 'data' field contains event ID.
      KCommandUserQuestionReplyIgnore = 5,


      /// Client sent KeepAlive message. 'data' unused, Should be set to 0.
      KCommandClientKeepalive      = 4
    };


    /** Alarm command.
     *
     * This structure contains command field to be used when sending
     * action requests to Alarm enabled clients.
     *
     * \see EAlarmCommand
     */
    struct TCommand 
    {
      TCommand(const unsigned int aCmd = 0,
               const unsigned int aData = 0) 
	: cmd(aCmd),
          data(aData) {}
      uint32_t cmd;             ///< Command
      uint32_t data;            ///< Data for command. (Is command specific)
    };



    /** Alarm event predefined types.
     */
    enum EAlarmEventType { 
      /** Unknown event type.
       *
       * This event type should never be sent
       * over to remote end.
       */
      KEventTypeUnknown          = 0,
      

      /** Raw event.
       *
       * The event type is RAW, meaning it has no standard meaning on
       * any node. Use of this type is discouraged but supported.
       */
      KEventTypeRaw              = 1,


      /** Question event.
       *
       * This event type can be used to carry standard form questions
       * from Server to client. The question can then be answered
       * using the TCommand element as return channel.  The 'Question'
       * can yield two values 'Yes' or 'No'. Its up to the client
       * implementation how it wishes to represent the question /
       * answer. ( OK / Cancel pair can be easily passed on as 'Yes' /
       * 'No' pair)
       */
      KEventTypeQuestion         = 2,


      /** Error event.
       *
       * This event is sent when a error of some form has happened.
       * Error is defined as an problem that has 1) already happened,
       * 2) is causing some trouble for the system operation.
       */
      KEventTypeError            = 3,


      /** Warning event.
       * 
       * This event is sent when some possible problem is
       * detected. Warning is defined as an problem that has 1) not
       * yet happened, 2) is likely to happen at some point if no
       * corrective action is taken, 3) will change to an 'Error' when
       * really happened.
       */
      KEventTypeWarning          = 4,


      /** Notification event.
       *
       * This event is sent when something important has happened / is
       * about to happen that the operator may want to
       * know. Notification is defined as an event that has 1) not
       * critical meaning for system operability, 2) may assist the
       * operator in maintaining an good overall insight to the task
       * at hand, 3)
       */
      KEventTypeNotification     = 5,


      /** Info event.
       *
       * This event is sent when some less critical event has been
       * triggered. Usually operators don't want to see these, unless
       * the system is being tested or evaluated.
       */
      KEventTypeInfo             = 6,


      /** Debug event.
       * 
       * This event is a pure debugging event. It could be sent as a
       * substitute of an 'dPrint' call. User should still consider
       * the bandwith, as sending all debuggin information over
       * network may not be wise, or even useful.
       */
      KEventTypeDebug            = 7
    };

    /** Flags for a Alarm event.
     */
    enum EAlarmEventFlag {
      /** Require user acknowledgement.
       *
       * If this flag is set, the user must reply by sending a command
       * 'KCommandUserAckEvent' with 'data' set to value of 'ID'.
       */
      KEventFlagRequireUserAck = (1<<0)
    };


    /** Alarm event.
     *
     * This structure contains 'alarm event' information.
     *
     * \see MaCI::Alarm::EAlarmEventType
     * \see MaCI::Alarm::EAlarmEventFlag
     */
    struct TAlarmEvent {
      TAlarmEvent(const unsigned int aEventType = KEventTypeUnknown,
                  const unsigned int aTimeout_s = 0,
                  const uint16_t aFlags = 0,
                  const uint32_t aID = 0)
        : type(aEventType),
          timeout_s(aTimeout_s),
          flags(aFlags),
          id(aID) {}
      
      uint8_t type;       ///< Event type. See type MaCI::Alarm::EAlarmEventType.
      uint8_t timeout_s;  ///< Event timeout in seconds. Zero if not set. 
      uint16_t flags;     ///< Event flags. See type MaCI::Alarm::EAlarmEventFlag.
      uint32_t id;        ///< Event ID. Used for identifying reply
    };


    /** Text container.
     * 
     * This structure carries freeform text. For displaying error
     * descriptions or describing questions. A TText element can never
     * occur alone, but must be right after a TAlarmEvent for to
     * function correctly. If a TText element is present in the
     * container alone, it will cause the packet decoding to fail.
     */
    struct TText {
      TText(const uint32_t aLength)
        : length(aLength) {}

      uint32_t length;
      char text[];
    };


    /** Type for heading. Same container as TText.
     */
    typedef TText THeadingText;


    /** Type for sourcename. Same container as TText.
     */
    typedef TText TSourceNameText;

  }
}

#endif
